/// <license>
/// Copyright (c) 2002-2008, DotNetNuke Corporation
/// All rights reserved
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
/// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
/// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
/// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
/// of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
/// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
/// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
/// DEALINGS IN THE SOFTWARE.
/// </license>

#region Using Statements

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Web.UI;

using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Modules.Actions;
using DotNetNuke.Framework;
using DotNetNuke.Security;
using DotNetNuke.Security.Permissions;
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.Packages;
using DNNSkin = DotNetNuke.UI.Skins.Skin;

using DotNetNuke.ModuleToolkit.Common;
using DotNetNuke.ModuleToolkit.Localization;
using DotNetNuke.ModuleToolkit.Modules.Extensions;
using DotNetNuke.ModuleToolkit.Modules.Skinning.SkinObjects;
using DotNetNuke.ModuleToolkit.Modules.Commands;
using DotNetNuke.ModuleToolkit.Modules.Skinning.Skins;

#endregion

namespace DotNetNuke.ModuleToolkit.Modules.Skinning
{
    /// -----------------------------------------------------------------------------
    /// <summary>
    /// The SkinnablePortalModuleBase class provides a base class for Skinnable Modules
    /// </summary>
    /// <remarks>
    /// <para>This class handles all of the skinning functionality required for a Skinnable
    /// Module.</para>
    /// <para><strong>Note to inheritors:</strong> override the OnInit method
    /// to change the skin control loading logic. If you wish to use your own system to determine
    /// the name of the skin file to load (instead of using the name of the ASCX file for this
    /// module control) simple override OnInit, change the <see cref="SkinnablePortalModuleBase.SkinFileName"/>
    /// property and call the base class (this class) version of OnInit (MyBase.OnInit/base.OnInit).
    /// The same can also be done with the <see cref="SkinnablePortalModuleBase.SkinName"/> to change
    /// the skin to load.</para>
    /// <para>If you want to provide portions of the UI that are consistent across all skins, you can manually
    /// place a <see cref="SkinnedControlHost"/> control anywher on the page. You DO NOT need to set anything
    /// other than an Id (and you probably don't even need that) and, of course, "runat=server". This means that
    /// when a skin is loaded into the module, it will be placed within that control, so you can place other controls
    /// around the <see cref="SkinnedControlHost"/> to provide UI that is constant across all skins. Note that placing
    /// multiple <see cref="SkinnedControlHost"/> controls is unsupported, and only the first will be used (although
    /// the actual results are untested). If no <see cref="SkinnedControlHost"/> control is found, one is automatically
    /// added to the end of the <see cref="Control.Controls"/> collection.</para>
    /// </remarks>
    /// <history>
    ///     [anurse]    12/22/2005  created
    ///     [cnurse]    01/30/2006  converted to C#/.NET 2
    /// </history>
    /// -----------------------------------------------------------------------------
    public class SkinnablePortalModuleBase :
        AdvancedModuleBase, 
        IActionable
    {

        #region Private Fields

        private const string CONTEXT_KEY = "DotNetNuke.ModuleToolkit.Skinning.Context.Module";

        private Hashtable _SharedData = new Hashtable();
        private SkinnedControlHost _SkinHost;
        private string _ViewName;

        #endregion

        protected string CreatePermission
        {
            get { return "CREATE"; }
        }

        protected string DeletePermission
        {
            get { return "DELETE"; }
        }

        protected string ModeratePermission
        {
            get { return "MODERATE"; }
        }


        #region Public Properties

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets a list of Extensions for the Module.
        /// </summary>
        /// <remarks>
        /// IMPORTANT: This list only contains Extensions that implement the <see cref="IExtension"/> interface
        /// </remarks>
        /// <history>
        ///     [cnurse]  10/12/2007  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public IList<IExtension> Extensions
        {
            get
            {
                return SkinHost.Extensions;
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets whether the current user has permission to create entities
        /// </summary>
        /// <history>
        /// 	[cnurse]	09/06/2007	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public virtual bool HasCreatePermission
        {
            get { return ModulePermissionController.HasModulePermission(ModuleId, TabId, CreatePermission); }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets whether the current user has permission to delete entities
        /// </summary>
        /// <history>
        /// 	[cnurse]	09/10/2007	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public virtual bool HasDeletePermission
        {
            get { return ModulePermissionController.HasModulePermission(ModuleId, TabId, DeletePermission); }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets whether the current user has permission to moderate entities
        /// </summary>
        /// <history>
        /// 	[cnurse]	09/06/2007	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public virtual bool HasModeratePermission
        {
            get { return ModulePermissionController.HasModulePermission(ModuleId, TabId, ModeratePermission); }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets and sets whether the module is in Add Mode
        /// </summary>
        /// <history>
        /// 	[cnurse]	04/19/2006	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public virtual bool IsAddMode
        {
            get { return false; }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets and sets whether the control is in Edit Mode
        /// </summary>
        /// <history>
        ///     [cnurse]  04/12/2006  Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public virtual bool IsEditMode
        {
            get { return false; }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets the Mode of the Control
        /// </summary>
        /// <history>
        /// 	[cnurse]	12/06/2006	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public string Mode
        {
            get
            {
                string _Mode = Null.NullString;
                if (Request.QueryString[Constants.PARAM_Mode] != null)
                {
                    _Mode = Request.QueryString[Constants.PARAM_Mode];
                }
                return _Mode;
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets a dictionary, stored in the Context, that can be used to hold data to be
        /// shared between SkinObjects and the Module
        /// </summary>
        /// <history>
        ///     [anurse]  05/19/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public Dictionary<string, object> SharedData
        {
            get
            {
                object obj = HttpContext.Current.Items[CONTEXT_KEY + ModuleId.ToString()];
                if ((obj == null) || !(obj is Dictionary<string, object>))
                {
                    Dictionary<string, object> sharedData = new Dictionary<string, object>();
                    HttpContext.Current.Items[CONTEXT_KEY + ModuleId.ToString()] = sharedData;
                    return sharedData;
                }
                return (Dictionary<string, object>)obj;
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets the file name that will be used to locate the skin control to load
        /// </summary>
        /// <history>
        ///     [anurse]  1/3/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public string SkinFileName
        {
            get
            {
                return SkinHost.ControlRelativePath;
            }
            set
            {
                SkinHost.ControlRelativePath = value;
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets the name of the current skin
        /// </summary>
        /// <history>
        ///     [anurse]  12/22/2005  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public string SkinName
        {
            get
            {
                return SkinHost.SkinName;
            }
            set
            {
                SkinHost.SkinName = value;
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets a list of Skin Objects for the Module.
        /// </summary>
        /// <remarks>
        /// IMPORTANT: This list only contains Skin Objects that implement the <see cref="ISkinObject"/> interface
        /// </remarks>
        /// <history>
        ///     [cnurse]  03/30/2006  created
        ///     [anurse]  05/02/2006  adapted for skinning engine rewrite
        /// </history>
        /// -----------------------------------------------------------------------------
        public IList<ISkinObject> SkinObjects
        {
            get
            {
                return SkinHost.SkinObjects;
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets a the skinned control host that will be used to host the skined content
        /// of this module
        /// </summary>
        /// <history>
        ///     [anurse]  05/02/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public SkinnedControlHost SkinHost
        {
            get
            {
                EnsureSkinHost();
                return _SkinHost;
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets the Folder where the Skins are located
        /// </summary>
        /// <value>A String</value>
        /// <history>
        ///     [anurse]  12/22/2005  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public string SkinsFolder
        {
            get
            {
                return String.Format("{0}/{1}", this.TemplateSourceDirectory, Constants.FOLDER_Skins);
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets and sets the curent View Name (or Skin Name)
        /// </summary>
        /// <history>
        /// 	[cnurse]	05/21/2006	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public string ViewName
        {
            get { return _ViewName; }
            private set { _ViewName = value; }
        }

        #endregion

        #region Private Methods

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Sets the SkinnedControlHost defaults
        /// </summary>
        /// <param name="host">The SKinnedControlHost</param>
        /// <history>
        ///     [cnurse]  03/30/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        private void SetSkinnedControlHostDefaults(SkinnedControlHost host)
        {
            // Hold the reskin until we've finished setting defaults
            host.SuspendReskinning();

            if (String.IsNullOrEmpty(host.SkinsFolder))
                host.SkinsFolder = this.SkinsFolder;
            if (String.IsNullOrEmpty(host.ControlRelativePath))
            {
                if (!this.ID.EndsWith(Constants.EXT_ASCX))
                    host.ControlRelativePath = String.Concat(this.ID, Constants.EXT_ASCX);
                else
                    host.ControlRelativePath = this.ID;
            }
            if (String.IsNullOrEmpty(host.SkinName))
            {
                string skinName = Convert.ToString(Settings[Constants.SETTING_ModuleSkin]);
                if (String.IsNullOrEmpty(skinName))
                {
                    skinName = Constants.SKIN_Default;
                }
                host.SkinName = skinName;
            }
            if (String.IsNullOrEmpty(host.FallbackSkinName))
                host.FallbackSkinName = Constants.SKIN_Default;

            host.ResumeReskinning();
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Find the contained SkinnedControlHost
        /// </summary>
        /// <history>
        ///     [cnurse]  03/30/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        private void FindSkinnedControlHost()
        {
            _SkinHost = FindSkinnedControlHost(Controls);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Find the contained SkinnedControlHost
        /// </summary>
        /// <param name="ctrls">The controls collection to search.</param>
        /// <returns>The SkinnedControlHost</returns>
        /// <history>
        ///     [cnurse]  03/30/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        private SkinnedControlHost FindSkinnedControlHost(ControlCollection ctrls)
        {
            return ControlUtils.FindChild<SkinnedControlHost>(ctrls);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Ensure the control has a SkinnedControlHost
        /// </summary>
        /// <history>
        ///     [cnurse]  03/30/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        private void EnsureSkinHost()
        {
            if (_SkinHost == null)
            {
                FindSkinnedControlHost();
                if (_SkinHost == null)
                {
                    _SkinHost = new SkinnedControlHost();
                    Controls.Add(_SkinHost);
                }
                SetSkinnedControlHostDefaults(_SkinHost);
            }
        }

        #endregion

        #region Protected Methods

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// CancelCommand runs when the cancel command button is clicked
        /// </summary>
        /// <param name="type">The entity type</param>
        /// <history>
        ///     [cnurse]  10/26/2007  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void CancelCommand(string type)
        {
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// DeleteCommand runs when the delete command button is clicked
        /// </summary>
        /// <param name="type">The entity type</param>
        /// <param name="entity">The entity</param>
        /// <param name="comment">A user submitted comment</param>
        /// <history>
        ///     [cnurse]  10/26/2007  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void DeleteCommand(string type, object entity, string comment)
        {
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Initializes the module
        /// </summary>
        /// <history>
        ///     [cnurse]  10/26/2007  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void InitializeModule()
        {
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Initializes the modules view
        /// </summary>
        /// <history>
        ///     [cnurse]  10/26/2007  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void InitializeView()
        {
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Loads the Skin into the module
        /// </summary>
        /// <history>
        ///     [cnurse]  03/30/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void LoadSkin()
        {
            //Create a SkinnedControlHost if necissary and set the defaults
            EnsureSkinHost();

            //Setup SkinObjects
            LoadSkinObjects();

        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Scans the controls collection for skin objects
        /// </summary>
        /// <history>
        ///     [cnurse]  03/30/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void LoadSkinObjects()
        {
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Runs before the Page_Init event is fired, and loads the skin
        /// </summary>
        /// <history>
        ///     [anurse]  12/22/2005  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected override void OnInit(EventArgs e)
        {
            try
            {
                //Initialize the Module
                InitializeModule();

                //Initialize the View
                InitializeView();

                //Load the Skin
                LoadSkin();
                 
                //Register Module Actions
                RegisterModuleActions();
            }
            catch (Exception exc)
            {
                Exceptions.ProcessModuleLoadException(this, exc);
            }
            base.OnInit(e);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// The ProcessSkinObject method attaches events to the SkinObjects in this Skin
        /// </summary>
        /// <param name="skinObject">SkinObject to process</param>
        /// <history>
        ///     [cnurse]    10/26/2007  Created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void ProcessSkinObject(ISkinObject skinObject)
        {
            if (skinObject is IModuleCommand)
            {
                IModuleCommand commandObject = (IModuleCommand)skinObject;
                commandObject.ModuleCommand += new ModuleCommandEventHandler(ModuleCommand);
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Processes the controls collection for skin objects
        /// </summary>
        /// <remarks>This method should be overriden in the derived class.</remarks>
        /// <history>
        ///     [cnurse]  03/30/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void ProcessSkinObjects()
        {
            //Iterate through SkinObjects in the base Skin to attach events, depending on the Interface
            //the Skin Object implements
            foreach (ISkinObject skinObject in SkinObjects)
            {
                ProcessSkinObject(skinObject);
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// PublishCommand runs when the publish command button is clicked
        /// </summary>
        /// <param name="type">The entity type</param>
        /// <param name="entity">The entity</param>
        /// <param name="comment">A user submitted comment</param>
        /// <history>
        ///     [cnurse]  10/26/2007  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void PublishCommand(string type, object entity, string comment)
        {
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Registers the ModuleActions on the DotNetNuke Skin
        /// </summary>
        /// <history>
        ///     [cnurse]  03/30/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void RegisterModuleActions()
        {
            //This finds a reference to the containing skin
            DNNSkin ParentSkin = DNNSkin.GetParentSkin(this);

            //We should always have a ParentSkin, but need to make sure
            if (ParentSkin != null)
                //Register our EventHandler as a listener on the ParentSkin so that it may tell us 
                //when a menu has been clicked.
                ParentSkin.RegisterModuleActionEvent(this.ModuleId, ModuleAction);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// RejectCommand runs when the reject command button is clicked
        /// </summary>
        /// <param name="type">The entity type</param>
        /// <param name="entity">The entity</param>
        /// <param name="comment">A user submitted comment</param>
        /// <history>
        ///     [cnurse]  10/26/2007  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void RejectCommand(string type, object entity, string comment)
        {
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// RestoreCommand runs when the restore command button is clicked
        /// </summary>
        /// <param name="type">The entity type</param>
        /// <param name="entity">The entity</param>
        /// <param name="comment">A user submitted comment</param>
        /// <history>
        ///     [cnurse]  11/01/2007  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void RestoreCommand(string type, object entity, string comment)
        {
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// SaveCommand runs when the save/update command button is clicked
        /// </summary>
        /// <param name="type">The entity type</param>
        /// <param name="entity">The entity</param>
        /// <param name="comment">A user submitted comment</param>
        /// <history>
        ///     [cnurse]  10/26/2007  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void SaveCommand(string type, object entity, string comment)
        {
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// The setView method sets the view
        /// </summary>
        /// <remarks></remarks>
        /// <param name="view">The view to use</param>
        /// <history>
        ///     [cnurse]    04/30/2006  Created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected void SetView(string view)
        {
            if (!view.EndsWith(".ascx"))
                view += ".ascx";
            ViewName = view;

            SkinnedControlHost subHost = SkinHost.FindSkinnedControlHost();

            if (subHost != null)
            {
                subHost.ControlRelativePath = view;
            }
            else if (SkinFileName != view)
            {
                SkinFileName = view;
                LoadSkin();
            }

            ProcessSkinObjects();
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// SubmitCommand runs when the submit command button is clicked
        /// </summary>
        /// <param name="type">The entity type</param>
        /// <param name="entity">The entity</param>
        /// <param name="comment">A user submitted comment</param>
        /// <history>
        ///     [cnurse]  10/26/2007  created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void SubmitCommand(string type, object entity, string comment)
        {
        }

        #endregion

        #region Public Methods

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Finds the control with the specified name and verifies that it is a SkinObject
        /// </summary>
        /// <param name="name">The name of the skin object to find</param>
        /// <returns>An instance of the skin object, or a null reference (Nothing in VB.net) if no such skin object exists</returns>
        /// <remarks>
        /// Note: If this method returns a null reference (Nothing in VB.net) a control with the name may exist
        /// but it does not implement the <see cref="ISkinObject"/> interface
        /// </remarks>
        /// <history>
        ///     [anurse]  05/02/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public ISkinObject FindSkinObject(string name)
        {
            return SkinHost.FindSkinObject(name);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Locates the specified resource within the current skin folder, and
        /// if it is not found, tries the fallback (default) skin folder
        /// </summary>
        /// <param name="relativePath">The relative path within the skin folder</param>
        /// <returns>The server path to the resource, or the empty string "" if the resource was not found</returns>
        /// <history>
        ///     [anurse]  12/22/2005  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public string MapSkinPath(string relativePath)
        {
            return SkinUtil.MapSkinPath(SkinsFolder, SkinName, Constants.SKIN_Default, relativePath);
        }

        #endregion

        #region Event Handlers

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Handles a module action that occurs
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// 	[anurse]	1/14/2006	created
        /// </history>
        /// -----------------------------------------------------------------------------
        protected virtual void ModuleAction(Object sender, ActionEventArgs e)
        {
            switch (e.Action.CommandName)
            {
                case Constants.CMD_ChangeSkin:
                    //update the Module Setting
                    SkinName = e.Action.CommandArgument;
                    ModuleController objModuleController = new ModuleController();
                    objModuleController.UpdateTabModuleSetting(this.TabModuleId, Constants.SETTING_ModuleSkin, SkinName);
                    
                    //Load the new skin
                    LoadSkin();
                    break;
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Command runs when a Command Button is clicked
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// 	[cnurse]	4/17/2006	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        private void ModuleCommand(object sender, ModuleCommandEventArgs e)
        {
            switch (e.CommandName)
            {
                case Constants.CMD_Cancel:
                    CancelCommand(e.CommandType);
                    break;
                case Constants.CMD_Delete:
                    DeleteCommand(e.CommandType, e.CommandArgument, e.Comment);
                    break;
                case Constants.CMD_Save:
                    SaveCommand(e.CommandType, e.CommandArgument, e.Comment);
                    break;
                case Constants.CMD_Publish:
                    PublishCommand(e.CommandType, e.CommandArgument, e.Comment);
                    break;
                case Constants.CMD_Reject:
                    RejectCommand(e.CommandType, e.CommandArgument, e.Comment);
                    break;
                case Constants.CMD_Restore:
                    RestoreCommand(e.CommandType, e.CommandArgument, e.Comment);
                    break;
                case Constants.CMD_Submit:
                    SubmitCommand(e.CommandType, e.CommandArgument, e.Comment);
                    break;
            }
        }

        #endregion

        #region IActionable Members

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets the custom Module Actions provided by this module
        /// </summary>
        /// <remarks>
        /// <strong>IMPORTANT!!!</strong> Always call this base class method first, add your
        /// custom actions to the collection and return that collection. Otherwise users
        /// will not be able to change skins, UNLESS you provide a UI to do so. If you wish to
        /// provide a UI to change skins and wish to hide these actions, you can override this
        /// method without calling the base class method.
        /// </remarks>
        /// <history>
        /// 	[cnurse]	3/18/2006	created
        /// </history>
        /// -----------------------------------------------------------------------------
        public virtual ModuleActionCollection ModuleActions
        {
            get
            {
                ModuleActionCollection Actions = new ModuleActionCollection();

                // Create the Extensions root
                ModuleAction extensionsRoot = new ModuleAction(GetNextActionID(), LocalizeString(Constants.TEXT_Extension), "", "", Constants.ACTIONIMAGE_Extensions, "", "", false, SecurityAccessLevel.Admin, IsEditable);

                // Add actions for each plug in
                foreach (ExtensionInfo extension in ExtensionController.GetExtensions(this.ModuleConfiguration.DesktopModuleID))
                {
                    if (!String.IsNullOrEmpty(extension.IExtensionClass))
                    {
                        //Instantiate the ExtensionBase
                        IExtension extensionControl = Reflection.CreateObject(extension.IExtensionClass, extension.IExtensionClass) as IExtension;
                        ModuleActionCollection extensionActions = extensionControl.GetModuleActions(this);

                        if (extensionActions.Count > 0)
                        {
                            //Create the Extension root
                            ModuleAction extensionRoot = new ModuleAction(GetNextActionID(), extensionControl.Name, "", "", extensionControl.ActionIcon, "", "", false, SecurityAccessLevel.Admin, IsEditable);

                            //Add Extension Actions
                            extensionRoot.Actions.AddRange(extensionActions);

                            //Add to Extensions Root
                            extensionsRoot.Actions.Add(extensionRoot);
                        }
                    }
                }

                //Add break
                extensionsRoot.Actions.Add(new ModuleAction(GetNextActionID(), "~", ""));

                //Add entry to install a new Skin
                extensionsRoot.Actions.Add(GetNextActionID(), LocalizeString(Constants.ACTION_InstallExtension), ModuleActionType.AddContent, "", "", Util.InstallURL(TabId, "Toolkit_Module_Extensions"), false, SecurityAccessLevel.Host, true, false);

                //Add Extension actions
                Actions.Add(extensionsRoot);

                //Add break
                Actions.Add(new ModuleAction(GetNextActionID(), "~", ""));

                // Add the change skin root
                ModuleAction skinRoot = new ModuleAction(GetNextActionID(), LocalizeString(Constants.TEXT_Skins), "", "", Constants.ACTIONIMAGE_Skins, "", "", false, SecurityAccessLevel.Admin, IsEditable);

                //Add entries for each skin in the skins folder
                skinRoot.Actions.Add(GetNextActionID(), LocalizeString( Constants.TEXT_Default), Constants.CMD_ChangeSkin, Constants.SKIN_Default, "", "", false, SecurityAccessLevel.Admin, IsEditable, false);

                foreach (SkinInfo skin in SkinController.GetSkins(this.ModuleConfiguration.DesktopModuleID))
                {
                    if (!skin.Name.Equals(Constants.SKIN_Default))
                    {
                        skinRoot.Actions.Add(GetNextActionID(), skin.Name, Constants.CMD_ChangeSkin, skin.Name, "", "", true, SecurityAccessLevel.Admin, IsEditable, false);
                    }
                }

                //Add break
                skinRoot.Actions.Add(new ModuleAction(GetNextActionID(), "~", ""));

                //Add entry to install a new Skin
                skinRoot.Actions.Add(GetNextActionID(), LocalizeString(Constants.ACTION_InstallSkin), ModuleActionType.AddContent, "", "", Util.InstallURL(TabId, "Toolkit_Module_Skins"), false, SecurityAccessLevel.Host, true, false);

                Actions.Add(skinRoot);

                return Actions;
            }
        }

        #endregion

    }
}
